package com.yansl.http.proxy;

import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.yansl.http.annotation.Param;
import com.yansl.http.handler.SpringHandler;
import com.yansl.http.model.HttpRequest;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;

/**
 * @description: 方法转换请求对象
 * @author: eshengtai
 * @create: 2022-12-17 16:49
 */
public class TransforRequestParse {
    /**
     * 请求方法
     */
    private HttpRequest httpRequest;
    /**
     * 参数值
     */
    private Object[] paramVals;

    public TransforRequestParse(final HttpRequest httpRequest, final Object[] paramVals) {
        this.httpRequest = httpRequest;
        this.paramVals = paramVals;
    }

    /**
     * 转换Get请求
     *
     * @return
     */
    public Object transforGet() {
        // 获取请求地址
        String url = httpRequest.getUrl();

        // 参数处理
        url = getRequestGetParams(url);

        return transfor(url, null);

    }

    /**
     * 转换POST请求
     *
     * @return
     */
    public Object transforPost() {

        // 获取请求地址
        String url = httpRequest.getUrl();

        // 参数处理
        if (paramVals.length > 1) {
            throw new RuntimeException("POST 只支持一个参数！！");
        }
        Map<String, Object> params = new HashMap<>();
        if (paramVals.length == 1) {
            params = BeanUtil.beanToMap(paramVals[0]);
        }
        return transfor(url, params);
    }

    private Object transfor(String url, Map<String, Object> bodyParams) {

        url = dyncUrlParams(url);

        // 返回值类型封装
        Class<?> returnType = httpRequest.getReturnType();
        TypeReference<Class<?>> typeReference = new TypeReference() {
            @Override
            public Type getType() {
                return returnType;
            }
        };

        // 设置header，token内容 , 触发过滤器
        Map<String, String> headMaps = new HashMap<>(0);

        // 发送请求
        String responseStr = httpRequest.getHttpCallHandler().request(httpRequest.getHttpMethod(), url, bodyParams, headMaps, (data) -> {
            // TODO 结果过滤器
            return data;
        }, httpRequest.getHttpIntercepter());
        boolean isResponseJson = StrUtil.isNotBlank(responseStr) && JSONUtil.isJson(responseStr);
        return isResponseJson ? JSONUtil.toBean(responseStr, typeReference, true) : responseStr;
    }

    /**
     * 动态url参数
     *
     * @return
     */
    private String dyncUrlParams(String url) {

        String[] dyncParams = extractDyncParams(url);
        for (String dyncParam : dyncParams) {
            String params = dyncParam.replace("{", "").replace("}", "");
            String paramVal = SpringHandler.getProperties(params);
            if (StrUtil.isBlank(paramVal)) {
                throw new RuntimeException("参数未配置$" + dyncParam);
            }
            url = url.replace("$" + dyncParam, paramVal);
        }

        if (url.indexOf("?") == -1) {
            url = url + "?";
        } else if (url.indexOf("?") > 0 && !url.endsWith("&")) {
            url = url + "&";
        }
        return url;
    }

    /**
     * 获取请求Get参数
     *
     * @param url
     */
    private String getRequestGetParams(String url) {
        StringBuffer urlParamsBuffer = new StringBuffer();
        urlParamsBuffer.append(url);
        Parameter[] parameters = httpRequest.getMethod().getParameters();
        if (Objects.nonNull(parameters) && parameters.length > 0) {
            urlParamsBuffer.append("?");
        }
        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            urlParamsBuffer.append(parameter.getAnnotation(Param.class).value());
            urlParamsBuffer.append("=" + paramVals[i]);
            urlParamsBuffer.append("&");
        }
        return urlParamsBuffer.toString();
    }

    /**
     * 抽取动态参数
     * 
     * @param content
     * @return
     */
    public static String[] extractDyncParams(String content) {
        String[] arr = new String[0];
        Pattern pattern = Pattern.compile("\\{([^}]*)\\}");
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            arr = Arrays.copyOf(arr, arr.length + 1);
            arr[arr.length - 1] = matcher.group();
        }
        return arr;
    }
}
